﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using AcAp = Autodesk.AutoCAD.ApplicationServices.Application;
namespace ChangDiTools.Tool {
    public static class UCSTools
    {
        [DllImport("acad.exe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "acedTrans")]
        private static extern int acedTrans(double[] point, IntPtr fromResbuf, IntPtr toResbuf, int displacement,
            double[] result);
        public enum CoordSystem
        {
            WCS=0,
            UCS,
            DCS,
            PSDCS
        }

        /// <summary>
        /// 将点或矢量从一个坐标系转换到另一个坐标系
        /// </summary>
        /// <param name="pt">坐标，表示点或位移矢量</param>
        /// <param name="from">源坐标系</param>
        /// <param name="to">目标坐标系</param>
        /// <param name="disp">位移矢量标记，1表示位移矢量，0表示点</param>
        /// <returns>返回转化后的坐标</returns>
        public static Point3d TranslateCoordinates(this Point3d pt, CoordSystem from, CoordSystem to, int disp)
        {
            double[] result=new double[3];
            acedTrans(pt.ToArray(), new ResultBuffer(new TypedValue(5003, from)).UnmanagedObject,
                new ResultBuffer(new TypedValue(5003, to)).UnmanagedObject,
                disp, result);
            return new Point3d(result);
        }
        /// <summary>
        /// 将点从一个坐标系转换到另一个坐标系
        /// </summary>
        /// <param name="pt">点</param>
        /// <param name="from">源坐标系</param>
        /// <param name="to">目标坐标系</param>
        /// <returns>返回转化后的坐标</returns>
        public static Point3d TranslateCoordinates(this Point3d pt, CoordSystem from, CoordSystem to)
        {
            return pt.TranslateCoordinates(from, to, 0);
        }
        /// <summary>
        /// 创建一个新的UCS
        /// </summary>
        /// <param name="db">数据库对象</param>
        /// <param name="UCSName">要创建的UCS名称</param>
        /// <returns>返回创建的UCS的Id</returns>
        public static ObjectId AddUCS(this Database db, string UCSName)
        {
            var trans = db.TransactionManager;
            UcsTable ut=trans.GetObject(db.UcsTableId,OpenMode.ForRead) as UcsTable;
            if (!ut.Has(UCSName))
            {
                UcsTableRecord utr=new UcsTableRecord(){Name = UCSName};
                ut.UpgradeOpen();
                ut.Add(utr);
                trans.AddNewlyCreatedDBObject(utr,true);
                ut.DowngradeOpen();
            }

            return ut[UCSName];
        }
        /// <summary>
        /// 将UCS表中已经存在的一个UCS设置为当前UCS
        /// </summary>
        /// <param name="db">数据库对象</param>
        /// <param name="UCSName">UCS名称</param>
        /// <returns>如果设置成功返回true，否则返回false</returns>
        public static bool SetCurrentUCS(this Database db, string UCSName)
        {
            var tr = db.TransactionManager;
            Editor ed = db.GetEditor();
            UcsTable ut=tr.GetObject(db.UcsTableId,OpenMode.ForRead) as UcsTable;
            if (!ut.Has(UCSName)) return false;
            ViewportTableRecord vtr = tr.GetObject(db.CurrentViewportTableRecordId(), OpenMode.ForWrite) as ViewportTableRecord;
            vtr.SetUcs(ut[UCSName]);
            vtr.DowngradeOpen();
            ed.UpdateTiledViewportsFromDatabase();
            return true;
        }
        /// <summary>
        /// 获取当前UCS
        /// </summary>
        /// <param name="db">数据库对象</param>
        /// <returns>返回当前UCS的ID</returns>
        public static ObjectId GetCurrentUCS(this Database db)
        {
            var tr = db.TransactionManager;
            Editor ed = db.GetEditor();
            UcsTable ut=tr.GetObject(db.UcsTableId,OpenMode.ForRead) as UcsTable;
            ViewportTableRecord vtr=tr.GetObject(db.CurrentViewportTableRecordId(),OpenMode.ForRead) as ViewportTableRecord;
            return vtr.UcsName;
        }
        /// <summary>
        /// 设置ucs的原点
        /// </summary>
        /// <param name="ucsid">ucs的ID</param>
        /// <param name="pt">要设置的ucs原点坐标</param>
        public static void SetUCSOrigin(this ObjectId ucsid, Point3d pt)
        {
            Database db = ucsid.Database;
            var trans = db.TransactionManager;
            UcsTableRecord utr=trans.GetObject(ucsid,OpenMode.ForRead) as UcsTableRecord;
            if(utr==null) return;//若ucs不存在，则返回
            utr.UpgradeOpen();
            utr.Origin = pt;//设置ucs的原点
            utr.DowngradeOpen();
        }
        /// <summary>
        /// 旋转ucs
        /// </summary>
        /// <param name="ucsId">ucsi的ID</param>
        /// <param name="rotateAngle">旋转角度</param>
        /// <param name="rotateAxis">旋转轴</param>
        public static void RotateUCS(this ObjectId ucsId, double rotateAngle, Vector3d rotateAxis)
        {
            Database db = ucsId.Database;
            var tr = db.TransactionManager;
            UcsTableRecord utr=tr.GetObject(db.UcsTableId,OpenMode.ForRead) as UcsTableRecord;
            if(utr==null) return;//若ucs不存在，则返回
            utr.UpgradeOpen();
            Vector3d xAxis = utr.XAxis;
            Vector3d yAxis = utr.YAxis;
            utr.XAxis = xAxis.RotateBy(rotateAngle * Math.PI / 180, rotateAxis);
            utr.YAxis = yAxis.RotateBy(rotateAngle * Math.PI / 180, rotateAxis);
            utr.DowngradeOpen();
        }
    }
}
